
/*
 * GeldkarteFunctions.java
 *
 * Created on 1. November 2006, 14:29
 *
 *  This file is part of JSmex.
 *
 *  JSmex is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  JSmex is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package jsmex.function;

import jsmex.*;
import jsmex.function.EF_BLOG_Record;
import jsmex.function.EF_LLOG_Record;
import jsmex.gui.GeldkarteGUI;
import jsmex.cardservice.GeldkarteCardService;
import jsmex.function.GkZTableModel;
import jsmex.function.GkLTableModel;
import opencard.core.terminal.ResponseAPDU;

/**
 *
 * @author Tobias Senger
 */
public class GeldkarteFunctions {
    
    private GeldkarteGUI gkgui = null;
    private GeldkarteCardService cs = null;
    private GkZTableModel gkztm = null;
    private GkLTableModel gkltm = null;
    private LogTracer lt = null;
    
    /** Creates a new instance of GeldkarteFunctions */
    public GeldkarteFunctions(GeldkarteCardService gkcs, LogTracer ltracer) {
        cs = gkcs;
        lt = ltracer;
        showGUI();
    }
    
    /**Creates and returns a new GkZTableModel
     *
     * @return
     */
    public GkZTableModel getGkZTableModel() {
        lt.info("called method getGkZTableModel().", this);
        if (gkztm == null) gkztm = new GkZTableModel(getBlogRecords());
        return gkztm;
    }
    
    /**Creates and returns a new GkLTableModel
     *
     * @return
     */
    public GkLTableModel getGkLTableModel() {
        lt.info("called method getGkLTableModel().", this);
        if (gkltm == null) gkltm = new GkLTableModel(getLlogRecords());
        return gkltm;
    }
    
    public void showGUI() {
        if (gkgui == null) gkgui = new GeldkarteGUI(this);
        lt.info("called method showGUI().", this);
        gkgui.setVisible(true);
    }
    
    /**Close the Geldkarte-GUI
     *
     */
    public void closeGUI() {
        lt.info("called method closeGUI().", this);
        gkgui.setVisible(false);
        gkgui.dispose();
        gkgui = null;
    }
    
    /** Inserts commas at the right position into the given String which contains an amount
     *
     * @param betrag String which contains an amount
     * @return Returns a formated String
     */
    private String formatBetragString(String betrag) {
        StringBuffer sb = new StringBuffer(betrag);
        sb.insert(4,",");
        while (sb.charAt(0)=='0') {
            sb.deleteCharAt(0);
        }
        if (sb.charAt(0)==',') sb.insert(0,'0');
        lt.info("called method formatBetragString(betrag: "+betrag+"). returns: "+sb.toString(), this);
        return sb.toString();
    }
    
    /** Returns a formated String which contains the current amount on the card.
     *
     * @return
     */
    public String getAktuellerBetrag() {
        lt.info("called method getAktuellerBetrag().", this);
        return formatBetragString(getBetraege(0));
    }
    
    /** Returns a formated String which contains the maximal amount on the card.
     *
     * @return
     */
    public String getMaximalBetrag() {
        lt.info("called method getMaximalBetrag().", this);
        return formatBetragString(getBetraege(1));
    }
    
    /** Returns a formated String which contains the maximal transfer amount on the card.
     *
     * @return
     */
    public String getMaxTransBetrag() {
        lt.info("called method getMaxTransBetrag().", this);
        return formatBetragString(getBetraege(2));
    }
    
    /**Returns the Geldkarte type
     *
     * @return
     */
    public String getKartentyp() {
        lt.info("called method getKartentyp().", this);
        cs.selectFID((byte)0x04,(byte)0x0C,cs.DF_BOERSE_AID);
        ResponseAPDU rsp = cs.readRecord((byte)0x01,(byte)0x19); // 0x19 = SFI von EF_BÖRSE
        int typ = JSmexTools.toUnsignedInt(rsp.data()[0]);
        if (typ==0) return new String("kontobezogene Börsenkarte");
        if (typ==0xFF) return new String("Wertkarte ohne Kontobezug");
        else return Integer.toString(typ);
    }
    
    /** Returns a formated String which contains the BLZ of the allocation account.
     *
     * @return
     */
    public String getBLZ() {
        lt.info("called method getBLZ().", this);
        cs.selectFID((byte)0x04,(byte)0x0C,cs.DF_BOERSE_AID);
        ResponseAPDU rsp = cs.readRecord((byte)0x01,(byte)0x19); // 0x19 = SFI von EF_BÖRSE
        return JSmexTools.BCDByteArrayToString(rsp.data(),1,5);
    }
    
    public String getKontoNr() {
        lt.info("called method getKontoNr().", this);
        cs.selectFID((byte)0x04,(byte)0x0C,cs.DF_BOERSE_AID);
        ResponseAPDU rsp = cs.readRecord((byte)0x01,(byte)0x19); // 0x19 = SFI von EF_BÖRSE
        return JSmexTools.BCDByteArrayToString(rsp.data(),5,10);
    }
    
    public String getPruefziffer() {
        lt.info("called method getPruefziffer().", this);
        cs.selectFID((byte)0x04,(byte)0x0C,cs.DF_BOERSE_AID);
        ResponseAPDU rsp = cs.readRecord((byte)0x01,(byte)0x19); // 0x19 = SFI von EF_BÖRSE
        return Integer.toString((rsp.data()[10]&(byte)0xF0));
    }
    
    public String getKennung() {
        lt.info("called method getKennung().", this);
        byte[] returnbyte = new byte[16];
        cs.selectFID((byte)0x04,(byte)0x0C,cs.DF_BOERSE_AID);
        ResponseAPDU rsp = cs.readRecord((byte)0x01,(byte)0x19); // 0x19 = SFI von EF_BÖRSE
        JSmexTools.copyByteArray(rsp.data(), returnbyte, 11, 16);
        return opencard.core.util.HexString.hexify(returnbyte);
    }
    
    /**Returns a unformated String which contains the maximal, the current or the maximal transfer amount,
     * depending on the paramter index.
     *
     * @param index Depending on index the method returns different amount:
     *  <ul>
     *      <li>0: current amount</li>
     *      <li>1: maximal amount</li>
     *      <li>3: max. transfer amount</li>
     *  </ul>
     * @return Returns a unformated String.
     */
    private String getBetraege(int index) {
        lt.info("called method getBetraege(index: "+Integer.toString(index)+").", this);
        cs.selectFID((byte)0x04,(byte)0x0C,cs.DF_BOERSE_AID);
        ResponseAPDU rsp = cs.readRecord((byte)0x01,(byte)0x18);
        return JSmexTools.BCDByteArrayToString(rsp.data(),index*3,index*3+3);
    }
    
    /**Returns an array of EF_BLOG_Record which contain the last three loading transfers.
     *
     * @return
     */
    private EF_BLOG_Record[] getBlogRecords() {
        lt.info("called method getBlogRecords().", this);
        EF_BLOG_Record[] recs = new EF_BLOG_Record[15];
        ResponseAPDU rsp;
        
        for (int i=0;i<15;i++) {
            rsp = cs.readRecord((byte)(i+1),(byte)0x1D); // 0x1D = SFI von EF_BLOG
            if (rsp.sw()!=0x6A83) recs[i] = new EF_BLOG_Record(rsp.data());
            else recs[i] = null;
        }
        return recs;
    }
    
    /**Returns an array of EF_LLOG_Record which contain the last 15 payment transfers.
     *
     * @return
     */
    private EF_LLOG_Record[] getLlogRecords() {
        lt.info("called method getLlogRecords().", this);
        EF_LLOG_Record[] recs = new EF_LLOG_Record[3];
        ResponseAPDU rsp;
        
        for (int i=0;i<3;i++) {
            rsp = cs.readRecord((byte)(i+1),(byte)0x1C); // 0x1D = SFI von EF_LLOG
            if (rsp.sw()!=0x6A83) recs[i] = new EF_LLOG_Record(rsp.data());
            else recs[i] = null;
        }
        return recs;
    }
    
}
